package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
import static com.leyou.common.constants.MQConstants.RoutingKeyConstants.ITEM_UP_KEY;

/**
 * @author 虎哥
 */
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private SpuDetailService spuDetailService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private SpecParamService paramService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        //健壮性判断page和rows参数
        if (page <= 0 || rows <= 0) {
            //不和规范
            throw new LyException(400, "分页参数不规范！");
        }
        //根据参数查询
        Page<Spu> spuPage = query().eq(id != null, "id", id)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(saleable != null, "saleable", saleable)
                .page(new Page<>(page, rows));
        //转换获取dto集合
        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(spuPage.getRecords());
        //遍历集合，获取并添加categoryName和brandName
        for (SpuDTO spuDTO : spuDTOList) {
            //新建方法获取分类名和品牌名
            getCategoryAndBrandName(spuDTO);
        }
        //获取总条数和总页数
        long total = spuPage.getTotal();
        long pageCurrent = spuPage.getPages();
        //返回
        return new PageDTO<>(total,pageCurrent,spuDTOList);
    }


    /**
     * 获取分类名和品牌名
     * @param spuDTO       商品Dto对象
     */
    private void getCategoryAndBrandName(SpuDTO spuDTO) {
        //获取三级分类的id
        List<Long> categoryIds = spuDTO.getCategoryIds();
        //查询category集合
        List<Category> categoryList = categoryService.listByIds(categoryIds);
        //判断集合是否为空
        if (!CollectionUtils.isEmpty(categoryList)) {
            //不为空，获取三级分类的名字
            String categoryName = categoryList.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);
        }
        //获取品牌id
        Long brandId = spuDTO.getBrandId();
        //查询brand
        Brand brand = brandService.getById(brandId);
        //判断是否为空
        if (brand != null) {
            //添加
            spuDTO.setBrandName(brand.getName());
        }
    }


    @Override
    @Transactional  //添加事务
    public void saveGoods(SpuDTO spuDTO) {
        //转换获取spu对象
        Spu spu = spuDTO.toEntity(Spu.class);
        //spu默认下架
        spu.setSaleable(false);
        //添加spu对象
        boolean save = save(spu);
        //判断添加是否成功
        if (!save) {
            //不成功报异常
            throw new LyException(400, "新增商品失败！");
        }
        //获取spuDetail对象
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
        //spuDetail对象spu_id赋值
        spuDetail.setSpuId(spu.getId());
        //添加商品详情
        save = spuDetailService.save(spuDetail);
        //判断是否成功，失败报异常
        if (!save) {
            //不成功报异常
            throw new LyException(400, "新增商品详情失败！");
        }
        //获取skuDto集合
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
       /* //遍历设置spuId
        List<Sku> skuList = new ArrayList<>();
        for (SkuDTO skuDTO : skuDTOList) {
            skuDTO.setSpuId(spu.getId());
            skuList.add(skuDTO.toEntity(Sku.class));
        }*/
        //用流改写
        List<Sku> skus = skuDTOList.stream().map(skuDTO -> {
            //每个sku赋值spu的id
            skuDTO.setSpuId(spu.getId());
            //销量赋值0
            skuDTO.setSold(0L);
            //每个sku赋值下架
            skuDTO.setSaleable(false);
            //转换sku，返回
            return skuDTO.toEntity(Sku.class);
        }).collect(Collectors.toList());
        //添加sku集合
        skuService.saveBatch(skus);
    }

    @Override
    @Transactional   //添加事务
    public void updateGoods(SpuDTO spuDTO) {
        //获取商品id
        Long spuDTOId = spuDTO.getId();
        //判断是否修改spu信息
        if (spuDTOId != null) {
            //转换获取spu对象
            Spu spu = spuDTO.toEntity(Spu.class);
            //禁止修改saleable
            spu.setSaleable(null);
            //更新spu对象
            boolean update = updateById(spu);
            //判断更新spu是否成功
            if (!update) {
                throw new LyException(400,"更新商品失败！");
            }
        }
        //获取detail对象
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        //判断是否为空
        if (spuDetailDTO != null && spuDetailDTO.getSpuId() != null) {
            //转换
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            //更新
            boolean update = spuDetailService.updateById(spuDetail);
            //判断更新是否成功
            if (!update) {
                throw new LyException(400, "更新商品详情表失败！");
            }
        }
        //获取skuDto集合
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        //判断是否有数据
        if (CollectionUtils.isEmpty(skuDTOList)) {
            //无数据，直接return
            return;
        }
        //有数据，转换为sku集合
        List<Sku> skuList = skuDTOList.stream().map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
        //按是否包含saleable分组,包含：则要删除，不包含：则增或改
        Map<Boolean, List<Sku>> map = skuList.stream().collect(Collectors.groupingBy(sku -> sku.getSaleable() != null));
        //获取sku要删除的集合
        List<Sku> skuDeleteList = map.get(false);
        //判断sku要删除的集合是否为空
        if (!CollectionUtils.isEmpty(skuDeleteList)) {
            //不为空，要删除，获取id集合
            List<Long> deleteIds = skuDeleteList.stream().map(Sku::getId).collect(Collectors.toList());
            //删除,批量删除无需判断返回值
            skuService.removeByIds(deleteIds);
        }
        //获取新增和修改的sku的集合
        List<Sku> skuSaveOrUpdateList = map.get(true);
        //判断集合是否为空
        if (!CollectionUtils.isEmpty(skuSaveOrUpdateList)) {
            //不为空，需要批量操作，全部赋值下架
            skuSaveOrUpdateList.forEach(sku -> sku.setSaleable(false));
            //新增或修改,批量操作无需判断返回值
            skuService.saveOrUpdateBatch(skuSaveOrUpdateList);
        }
        /*//遍历集合，
        for (Sku sku : skuList) {
            //获取sku的id
            Long skuId = sku.getId();
            //判断是否存在
            if (skuId != null) {
                //获取saleable
                Boolean saleable = sku.getSaleable();
                //判断saleable
                if (saleable) {
                    //saleable为true表示新增或者更新
                    boolean update = skuService.saveOrUpdate(sku);
                    if (!update) {
                        throw new LyException(400, "更新sku表失败！");
                    }
                } else {
                    //false表示删除
                    boolean remove = skuService.removeById(skuId);
                    if (!remove) {
                        throw new LyException(400, "删除sku表信息失败！");
                    }
                }
            }
        }*/
    }

    @Override
    @Transactional   //添加事务
    public void updateSaleable(Long id, Boolean saleable) {
        //判断id和saleable是否为空
        if (id == null || saleable == null) {
            //有一个为空就没意思
            throw new LyException(400, "参数不符合规范！");
        }
        //新建一个对象，并赋值
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        //更新
        boolean update = updateById(spu);
        //判断是否更新成功
        if (!update) {
            throw new LyException(400, "更新spu表上下架失败！");
        }
        //更新sku表
        update = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        //判断
        if (!update) {
            throw new LyException(400, "更新sku表上下架失败！");
        }
        //判断上架还是下架
        String routingKey = saleable ? ITEM_UP_KEY : ITEM_DOWN_KEY;
        //MQ发送消息
        amqpTemplate.convertAndSend(ITEM_EXCHANGE_NAME,routingKey,id);
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        //获取spu对象，spuDetail对象
        Spu spu = getById(id);
        SpuDetail spuDetail = spuDetailService.getById(id);
        //判断是否存在
        if (spu == null || spuDetail == null) {
            throw new LyException(400, "该商品id不存在！");
        }
        //转换为Dto
        SpuDTO spuDTO = new SpuDTO(spu);
        SpuDetailDTO spuDetailDTO = new SpuDetailDTO(spuDetail);
        //给spuDto赋值spuDetailDTO
        spuDTO.setSpuDetail(spuDetailDTO);
        //获取分类名和品牌名
        getCategoryAndBrandName(spuDTO);
        //根据spu id 获取sku集合
        List<Sku> skuList = skuService.query().eq("spu_id", id).list();
        //判断是否存在
        if (CollectionUtils.isEmpty(skuList)) {
            throw new LyException(400, "该商品id不存在!");
        }
        //转换赋值
        List<SkuDTO> skuDTOList = SkuDTO.convertEntityList(skuList);
        spuDTO.setSkus(skuDTOList);
        return spuDTO;
    }

    @Override
    public List<SpecParamDTO> querySpecValuesBySpuId(Long spuId, Boolean searching) {
        //根据spu的id获取spu对象
        Spu spu = getById(spuId);
        //判断是否为空
        if (spu == null) {
            throw new LyException(400, "该id不存在！");
        }
        //获取分类id
        Long categoryId = spu.getCid3();
        //获取规格参数集合
        List<SpecParamDTO> specParamDTOList = paramService.querySpecParamsByCondition(categoryId, null, searching);
        //获取detail对象
        SpuDetail spuDetail = spuDetailService.getById(spuId);
        //获取detail对象的规格参数值
        String specification = spuDetail.getSpecification();
        //将规格参数值转换为map集合
        Map<Long, Object> map = JsonUtils.toMap(specification, Long.class, Object.class);
        //遍历集合，给规格参数value赋值
        for (SpecParamDTO specParamDTO : specParamDTOList) {
            //给value赋值
            specParamDTO.setValue(map.get(specParamDTO.getId()));
        }
        return specParamDTOList;
    }
}

